package com.qining618.common.core.weixin.util;

import com.alibaba.fastjson.JSON;
import com.qining618.common.core.weixin.bean.wxa.WxaDPhoneInfo;
import com.qining618.common.core.weixin.bean.wxa.WxaDUserInfo;
import com.qining618.common.core.weixin.bean.wxa.WxaUserInfo;
import com.qining618.common.core.weixin.mp.aes.PKCS7Encoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;

/**
 * @author flt
 * @date 2019-09-25
 */
@Slf4j
public class WxaUtil {

    /**
     * 解密用户数据
     *
     * @param sessionKey session key
     * @param encryptedData 加密数据
     * @param iv 加密算法的初始向量
     * @return WxaDUserInfo 解密失败 返回null
     */
    public static WxaDUserInfo decryptUserInfo(String sessionKey, String encryptedData, String iv) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            Key sKeySpec = new SecretKeySpec(Base64.decodeBase64(sessionKey), "AES");
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, new IvParameterSpec(Base64.decodeBase64(iv)));
            byte[] resultByte = cipher.doFinal(Base64.decodeBase64(encryptedData));
            String data = new String(PKCS7Encoder.decode(resultByte), StandardCharsets.UTF_8);
            return JSON.parseObject(data, WxaDUserInfo.class);
        } catch (Exception e) {
            log.error("解密用户数据失败", e);
        }
        return null;
    }

    /**
     * 解密手机号信息
     *
     * @param sessionKey session key
     * @param encryptedData 加密数据
     * @param iv 加密算法的初始向量
     * @return WxaDUserInfo 解密失败 返回null
     */
    public static WxaDPhoneInfo decrypPhoneInfo(String sessionKey, String encryptedData, String iv) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            Key sKeySpec = new SecretKeySpec(Base64.decodeBase64(sessionKey), "AES");
            cipher.init(2, sKeySpec, new IvParameterSpec(Base64.decodeBase64(iv)));
            byte[] resultByte = cipher.doFinal(Base64.decodeBase64(encryptedData));
            String data = new String(PKCS7Encoder.decode(resultByte), StandardCharsets.UTF_8);
            return JSON.parseObject(data, WxaDPhoneInfo.class);
        } catch (Exception e) {
            log.error("解密手机号信息失败", e);
            return null;
        }
    }

    /**
     * 校验wx.getUserInfo rawData 签名,同时返回 userinfo
     * @param sessionKey session_key
     * @param rawData rawData
     * @param signature signature
     * @return WxaUserInfo 签名校验失败时，返回null
     */
    public static WxaUserInfo validateUserInfo(String sessionKey, String rawData, String signature) {
        try {
            if (DigestUtils.sha1Hex(rawData + sessionKey).equals(signature)) {
                return JSON.parseObject(rawData, WxaUserInfo.class);
            }
        } catch (Exception e) {
            log.error("校验签名失败", e);
        }
        return null;
    }
}
